/**
 * Subclass van ui_FilterWidget
 */
#include "filterwidget.h"
#include <QDebug>
#include <QFileDialog>
#include <iostream.h>

/**
 * Constructor
 */
FilterWidget::FilterWidget(QWidget *parent) : QWidget(parent)
{
	setupUi(this);
	filter=Value(objectValue);
	constantValues=ConstantValues::getInstance();
	signalMapper = new QSignalMapper(this);

	nextHeight=5;
	//Set validators
	connect(signalMapper, SIGNAL(mapped(const QString &)),this, SLOT(processClick(const QString &)));

}
void FilterWidget::init(Value filterValue)
{
	filter=filterValue;
	generateForm();
	filter.clear();
}
void FilterWidget::generateForm()
{
	Path *path=NULL;
	Value filterValue=Value(objectValue);
	int matchCount=0;
	QString selected="";
	QString previousSelected="";
	QString fieldPath;
	QString nextFilterPath="";
	
	QString pathValue;
	int go;
	std::vector <std::string> filterPaths =constantValues->filters.getMemberNames();
	QString filterPath=".";
	QString editValue="";
	/** Methode 2 - itereren over constantvalues
	*/
	while(go)
	{
		go=0;
		filterValue=Path(QString(filterPath).toStdString()).resolve(constantValues->filters);
		//Check for enum or field
		if(!filterValue["enum"].empty())
		{
			//Check if the enum field is allready added to the form
			if(findChild<QWidget *>(filterPath))
			{	
				QComboBox *cb=findChild<QComboBox *>(filterPath);
				previousSelected=cb->property("previousSelected").toString();
				selected=cb->currentText();
				cb->setProperty("previousSelected",selected);

				if(previousSelected.compare(selected)!= 0)
					cleanPathChildren(filterPath);

				//Check if enum field is changed, this will be implemented later..for now only "" 
				if(selected!="")
				{
					if(filterPath!=".")
						filterPath=filterPath+".";
					filterPath=filterPath+selected;
					go=1;
					continue;
				}
				return;
			}
			else
			{
				editValue=="";
				editValue=getEnumEditValue(filterPath);
				if(editValue!="")
				{
					addEnum(editValue,filterPath,filterPath);
					if(filterPath!=".")
						filterPath=filterPath+".";
					filterPath=filterPath+editValue;
					cleanPathChildren(filterPath);
					go=1;
					continue;
				}
				else
				{
					addEnum("",filterPath,filterPath);
					cleanPathChildren(filterPath);
				}
				return;
			}
		}
		//Fix the text field.
		else
		{
			filterPaths = filterValue.getMemberNames();
			//Iterate over values
			for(int pathCount=1; pathCount<filterValue["value"].size(); pathCount++)
			{
				//Skip all .u32 values, except the (priority).
				if(filterPath==".u32" && pathCount !=3)
					continue;
	
				fieldPath=filterPath+".value."+QString().setNum(pathCount);
				//Check if field exist
				if(findChild<QWidget *>(fieldPath))
				{
				}
				else
				{
					editValue=="";
					editValue=getFieldEditValue(filterPath,pathCount);
					if(editValue!="")
					{
						addField(editValue,filterPath,fieldPath);
					}
					else
					{
						addField("",filterPath,fieldPath);
					}
				}
			}
			//Search for new options
			for(int pathCount=0; pathCount<filterPaths.size(); pathCount++)
			{
				if(filterPaths[pathCount]=="text" || filterPaths[pathCount]=="value" || filterPaths[pathCount]=="name")
					continue;
				//Check if option is enum.
				if(filterValue[filterPaths[pathCount]]["enum"].asString()=="1")
				{
					nextFilterPath=filterPath+"."+QString().fromStdString(filterPaths[pathCount]);
					go=1;
				}
				else 
				{
					for(int valueCount=1; valueCount < filterValue[filterPaths[pathCount]]["value"].size(); valueCount++)
					{
						
						fieldPath=filterPath+"."+QString().fromStdString(filterPaths[pathCount])+".value."+QString().setNum(valueCount);
						pathValue=filterPath+"."+QString().fromStdString(filterPaths[pathCount]);
						//Check if field exist.
						if(findChild<QWidget *>(fieldPath))
						{
			
						}
						else
						{
							editValue=="";
							editValue=getFieldEditValue(filterPath+"."+QString().fromStdString(filterPaths[pathCount]),valueCount);
									
							if(editValue!="")
							{
								addField(editValue,pathValue,fieldPath);	
							}	
							else
							{
								addField("",pathValue,fieldPath);						
							}		
						}	
					}	
				}		
			}	
			filterPath=nextFilterPath;
		}
	}
	
}
//Deprecated
void FilterWidget::addEnumMatchToFilter(QString filterPath)
{
}

Value FilterWidget::getFilter()
{
	QString path=".";
	QString tmpValue="";
	QStringList tmpList;
	Value tmpFilter;
	int matchCount=0;
	QRegExp labelRx("*label");
	QRegExp valueRx("*.value.*");
	labelRx.setPatternSyntax(QRegExp::Wildcard);
	valueRx.setPatternSyntax(QRegExp::Wildcard);
	QList<QWidget *> widgets= findChildren<QWidget *>(QRegExp(QRegExp::escape(path)));
	filter.clear();
	filter=Value(arrayValue);

	for(int widgetCount=0; widgetCount<widgets.size(); widgetCount++)
	{

		//Skip path if label
		if(labelRx.exactMatch(widgets[widgetCount]->objectName()))
			continue;

		//Check if value
		if(valueRx.exactMatch(widgets[widgetCount]->objectName()))
		{
			tmpList.clear();
			tmpValue=((QLineEdit*)widgets[widgetCount])->text();
			if(tmpValue!="")
			{
				tmpList << widgets[widgetCount]->objectName().split(".value.");
				tmpFilter[QString(tmpList[0]).toStdString()]["value"][QString(tmpList[1]).toInt()]=QString(tmpValue).toStdString();
			}
		}
		else
		{
			QComboBox *cb=findChild<QComboBox *>(widgets[widgetCount]->objectName());
			tmpValue=cb->currentText();
			if(tmpValue!="")
			{
				if(path!=".")
					tmpValue=widgets[widgetCount]->objectName()+"."+tmpValue;
				else
					tmpValue=widgets[widgetCount]->objectName()+tmpValue;
				tmpFilter[QString(tmpValue).toStdString()];
			}
		}
		path="";
	}


	std::vector <std::string> filterPaths=tmpFilter.getMemberNames();
	for(int matchCount=0; matchCount<filterPaths.size(); matchCount++)
	{
		//Check if value.
		if(tmpFilter[filterPaths[matchCount]].isMember("value"))
		{
			for(int valueCount=1; valueCount<tmpFilter[filterPaths[matchCount]]["value"].size(); valueCount++)
			{
				if(!tmpFilter[filterPaths[matchCount]]["value"][valueCount].empty())
					filter[matchCount+1]["value"][valueCount]=tmpFilter[filterPaths[matchCount]]["value"][valueCount];
			}
		}
		filter[matchCount+1]["path"]=filterPaths[matchCount];

	}
	return filter;

}
QString FilterWidget::getFieldEditValue(QString filterPath,int nr)
{
	for(int i=1; i<filter.size(); i++)
	{
		if(QString().fromStdString(filter[i]["path"].asString())==filterPath)
			return QString().fromStdString(filter[i]["value"][nr].asString());
	}
	return "";
}

QString FilterWidget::getEnumEditValue(QString filterPath)
{
	QString searchPath="";
	Value filterValue=Value(objectValue);
	filterValue=Path(QString(filterPath).toStdString()).resolve(constantValues->filters);
	std::vector <std::string> filterPaths=filterValue.getMemberNames();
	for(int i=0; i<filterPaths.size(); i++)
	{
		if(filterPaths[i]!="enum" && filterPaths[i]!="name")	 {
				if(filterPath!=".")
					searchPath=filterPath+"."+QString().fromStdString(filterPaths[i]);
				else
					searchPath=filterPath+QString().fromStdString(filterPaths[i]);
				if(findPath(searchPath)!=-1)
				{
					return QString().fromStdString(filterPaths[i]);
				}
		}	
	}
	return "";
}
void FilterWidget::cleanPathChildren(QString path)
{
	QList<QWidget *> widgets= findChildren<QWidget *>(QRegExp(QRegExp::escape(path)));
	for(int widgetCount=0; widgetCount<widgets.size(); widgetCount++)
	{
		if(widgets[widgetCount]->objectName()==path+"label" || widgets[widgetCount]->objectName()==path)
			continue;
		delete widgets[widgetCount];	
		nextHeight=nextHeight-34/2;
	}
}
void FilterWidget::addEnum(QString value,QString pathValue,QString mappingID)
{
	Path *path=NULL;
	Value filterValue=Value(objectValue);	
	int indexEditValue;
	int currentIndex=0;

	path=new Path(QString(pathValue).toStdString());
	filterValue=path->resolve(constantValues->filters);

	std::vector <std::string> filterPaths=filterValue.getMemberNames();
	QStringList list=QStringList();

	list << "";

	//Fix label
	QString labelValue=QString().fromStdString(filterValue["name"].asString());
	QLabel *label=new QLabel(labelValue,this);
	label->setObjectName(mappingID+"label");
	label->setGeometry(0,nextHeight,191,29);
	label->show();

	//Fix combobox
	for(int i=0; i<filterPaths.size(); i++)
	{
		if(filterPaths[i]!="enum" && filterPaths[i]!="name")
		{
			currentIndex++;
			if(QString().fromStdString(filterPaths[i])==value)
				indexEditValue=currentIndex;
			list << QString().fromStdString(filterPaths[i]);

		}
	}
	QComboBox *cb=new QComboBox(this);
	cb->setObjectName(mappingID);
	cb->setGeometry(200,nextHeight, 153, 30 );
	cb->addItems(list);
	cb->setProperty("previousSelected",value);
	if(value!="")
		cb->setCurrentIndex(indexEditValue);
	cb->show();
	
	signalMapper->setMapping(cb,mappingID);
	connect(cb, SIGNAL(activated(QString)), signalMapper, SLOT(map()));

	//Update next free form space position.
	nextHeight=nextHeight+34;
}
void FilterWidget::addField(QString value,QString pathValue,QString mappingID)
{
	Path *path=NULL;
	Value filterValue=Value(objectValue);

	path=new Path(QString(pathValue).toStdString());
	filterValue=path->resolve(constantValues->filters);

	//Fix label
	QString labelValue=QString().fromStdString(filterValue["name"].asString());
	QLabel *label=new QLabel(labelValue,this);
	label->setObjectName(mappingID+"label");
	label->setGeometry(0,nextHeight,191,29);
	label->show();

	QLineEdit *le=new QLineEdit(this);
	le->setGeometry(200,nextHeight, 153, 30 );
	le->setObjectName(mappingID);
	le->setText(value);
	le->show();
	signalMapper->setMapping(le,mappingID);
	//connect(le, SIGNAL(editingFinished()), signalMapper, SLOT(map()));
	nextHeight=nextHeight+34;
}

//Search for path in current 'filter'..
int FilterWidget::findPath(QString path)
{
	for(int i=1; i<filter.size(); i++)
	{
		if(path==QString().fromStdString(filter[i]["path"].asString()))
		{
			return i;
		}
	}
	return -1;
}


void FilterWidget::processClick(const QString &mappingID)
{
	generateForm();
}

